{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-spectrum/radio';
import packageData from '@react-spectrum/radio/package.json';
import {HeaderInfo, PropTable, PageDescription, VersionBadge, ClassAPI} from '@react-spectrum/docs';

```jsx import
import {Radio, RadioGroup} from '@react-spectrum/radio';
import {Flex} from '@react-spectrum/layout';
```

---
category: Forms
keywords: [radio group, radio]
---

# RadioGroup

<PageDescription>{docs.exports.Radio.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['RadioGroup', 'Radio']}
  sourceData={[
  {type: 'Spectrum', url: 'https://spectrum.adobe.com/page/radio-button/'}
  ]}
  since="3.0.0" />

## Example

```tsx example
<RadioGroup label="Favorite pet">
  <Radio value="dogs">Dogs</Radio>
  <Radio value="cats">Cats</Radio>
</RadioGroup>
```

## Content

RadioGroup accepts multiple Radio elements as children.
Each Radio represents an option that can be selected, labeled by its children.

**Note:** A Radio cannot be used outside of a RadioGroup.

## Value

RadioGroup only allows single selection. An initial, uncontrolled value can be provided to the RadioGroup using the `defaultValue` prop.
Alternatively, a controlled value can be provided using the `value` prop.

```tsx example
function Example() {
  let [selected, setSelected] = React.useState('yes');

  return (
    <Flex gap="size-300">
      <RadioGroup label="Are you a wizard? (uncontrolled)" defaultValue="yes">
        <Radio value="yes">Yes</Radio>
        <Radio value="no">No</Radio>
      </RadioGroup>

      <RadioGroup label="Are you a wizard? (controlled)" value={selected} onChange={setSelected}>
        <Radio value="yes">Yes</Radio>
        <Radio value="no">No</Radio>
      </RadioGroup>
    </Flex>
  );
}
```

### HTML forms

RadioGroup supports the `name` prop, paired with the Radio `value` prop, for integration with HTML forms.

```tsx example
<RadioGroup label="Favorite pet" name="pet">
  <Radio value="dogs">Dogs</Radio>
  <Radio value="cats">Cats</Radio>
</RadioGroup>
```

## Labeling
A visual label should be provided for the RadioGroup using the `label` prop. If the RadioGroup is required, the `isRequired` and
`necessityIndicator` props can be used to show a required state.

```tsx example
<Flex gap="size-300" wrap>
  <RadioGroup label="Favorite avatar">
    <Radio value="wizard">Wizard</Radio>
    <Radio value="dragon">Dragon</Radio>
  </RadioGroup>

  <RadioGroup label="Favorite avatar" isRequired necessityIndicator="icon">
    <Radio value="wizard">Wizard</Radio>
    <Radio value="dragon">Dragon</Radio>
  </RadioGroup>

  <RadioGroup label="Favorite avatar" isRequired necessityIndicator="label">
    <Radio value="wizard">Wizard</Radio>
    <Radio value="dragon">Dragon</Radio>
  </RadioGroup>

  <RadioGroup label="Favorite avatar" necessityIndicator="label">
   <Radio value="wizard">Wizard</Radio>
   <Radio value="dragon">Dragon</Radio>
  </RadioGroup>
</Flex>
```
### Accessibility

If a visible label isn't specified for a RadioGroup, an `aria-label` must be provided for accessibility. If the field is labeled by a separate element, an `aria-labelledby` prop must be provided using the id of the labeling element instead.

Radio elements should always have a visible label.

### Internationalization

To internationalize a RadioGroup, a localized string should be passed to the `label` prop and as the child content of the Radio elements.
For languages that are read right-to-left (e.g. Hebrew and Arabic), the Radio is automatically placed on the right side of the text. When the necessityIndicator prop is set to "label", a localized string will be provided for "(required)" or "(optional)" automatically.

## Events

RadioGroup accepts an `onChange` prop, which is triggered when a user changes the selected value.
The example below uses `onChange` to log how the user is interacting with the component.

```tsx example
function Example() {
  let [selected, setSelected] = React.useState(null);

  return (
    <>
      <RadioGroup label="Favorite avatar" value={selected} onChange={setSelected}>
        <Radio value="wizard">Wizard</Radio>
        <Radio value="dragon">Dragon</Radio>
      </RadioGroup>
      <div>You have selected: {selected}</div>
    </>
  );
}
```

## Validation

RadioGroup supports the `isRequired` prop to ensure the user selects an option, as well as custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more.

When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically.

```tsx example
import {Form, ButtonGroup, Button} from '@adobe/react-spectrum';

<Form validationBehavior="native">
  {/*- begin highlight -*/}
  <RadioGroup label="Favorite pet" name="pet" isRequired>
  {/*- end highlight -*/}
    <Radio value="dogs">Dog</Radio>
    <Radio value="cats">Cat</Radio>
    <Radio value="dragon">Dragon</Radio>
  </RadioGroup>
  <ButtonGroup>
    <Button type="submit" variant="primary">Submit</Button>
    <Button type="reset" variant="secondary">Reset</Button>
  </ButtonGroup>
</Form>
```

By default, `RadioGroup` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors.

## RadioGroup props

<PropTable component={docs.exports.RadioGroup} links={docs.links} />

## Radio props

<PropTable component={docs.exports.Radio} links={docs.links} />

## Visual options

### Orientation

RadioGroups are vertically oriented by default.
The `orientation` prop can be used to change the orientation to horizontal.

```tsx example
<RadioGroup label="Favorite avatar" orientation="horizontal">
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon">Dragon</Radio>
</RadioGroup>
```

### Label position and alignment
[View guidelines](https://spectrum.adobe.com/page/radio-button/#Label)

By default, the label is positioned above the RadioGroup.
The `labelPosition` prop can be used to position the label to the side. The `labelAlign` prop can
be used to align the label as "start" or "end".
For left-to-right (LTR) languages, "start" refers to the left most edge of the RadioGroup
and "end" refers to the right most edge. For right-to-left (RTL) languages, this is flipped.

```tsx example
<RadioGroup label="Favorite avatar" labelPosition="side" labelAlign="end">
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon">Dragon</Radio>
</RadioGroup>
```

### Help text
[View guidelines](https://spectrum.adobe.com/page/radio-group/#Help-text-(description-and-error-message))

Both a description and an error message can be supplied to a RadioGroup. The description is always visible unless `isInvalid` is true and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized.

```tsx example
function Example() {
  let [selected, setSelected] = React.useState('dogs');
  let isValid = selected === 'dogs';

  return (
    <RadioGroup
      aria-label="Favorite pet"
      onChange={setSelected}
      isInvalid={!isValid}
      description="Please select a pet."
      errorMessage={
        selected === 'cats'
          ? 'No cats allowed.'
          : 'Please select dogs.'
      }>
      <Radio value="dogs">
        Dogs
      </Radio>
      <Radio value="cats">
        Cats
      </Radio>
      <Radio value="dragons">
        Dragons
      </Radio>
    </RadioGroup>
  );
}
```

### Contextual help

A [ContextualHelp](ContextualHelp.html) element may be placed next to the label to provide additional information or help about a RadioGroup.

```tsx example
import {Content, ContextualHelp, Heading} from '@adobe/react-spectrum';

<RadioGroup
  label="T-shirt size"
  contextualHelp={
    <ContextualHelp variant="info">
      <Heading>Size and fit</Heading>
      <Content>Our sizes run on the small side. Choose a size up from your usual.</Content>
    </ContextualHelp>
  }>
  <Radio value="S">Small</Radio>
  <Radio value="M">Medium</Radio>
  <Radio value="L">Large</Radio>
</RadioGroup>
```

### Disabled
[View guidelines](https://spectrum.adobe.com/page/radio-button/#Disabled)

```tsx example
<RadioGroup label="Favorite avatar" isDisabled>
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon">Dragon</Radio>
</RadioGroup>
```

```tsx example
<RadioGroup label="Favorite avatar">
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon" isDisabled>Dragon</Radio>
</RadioGroup>
```

### Read only
[View guidelines](https://spectrum.adobe.com/page/radio-button/#Read-only)

The isReadOnly prop makes the selection immutable. Unlike isDisabled, the RadioGroup remains focusable.
See the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly) for more information.

```tsx example
<RadioGroup label="Favorite avatar" defaultValue="wizard" isReadOnly>
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon">Dragon</Radio>
</RadioGroup>
```

### Emphasized
[View guidelines](https://spectrum.adobe.com/page/radio-button/#Emphasis)

```tsx example
<RadioGroup label="Favorite avatar" defaultValue="dragon" isEmphasized>
  <Radio value="wizard">Wizard</Radio>
  <Radio value="dragon">Dragon</Radio>
</RadioGroup>
```
